package com.ruanyun.tio.net.server.handler;

import com.ruanyun.tio.net.common.PacketVo;
import com.ruanyun.tio.net.common.command.Command;
import com.ruanyun.tio.net.common.command.CommandHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tio.core.ChannelContext;
import org.tio.utils.hutool.ClassScanAnnotationHandler;
import org.tio.utils.hutool.ClassUtil;
import org.tio.utils.json.Json;

import java.util.Map;
import java.util.TreeMap;

/**
 * @author tanyaowu 
 * 2017年9月7日 下午5:39:49
 */
public class PacketDispatcher {
	private static Logger log = LoggerFactory.getLogger(PacketDispatcher.class);

	/**
	 * 路径和对象映射
	 * key: Command
	 * value: object
	 */
	public static Map<Command, ServerHandler> handlerMap = new TreeMap<>();
//	static {
//
//        handlerMap.put(Command.s1, new HardwareHeartbeatHandler());
//		handlerMap.put(Command.s2, new HardwareLoginHandler());
//    }
	/**
	 * 路径和class映射
	 * 只是用来打印的
	 * key: Command
	 * value: Class
	 */
	public Map<Command, Class<?>> pathClassMap = new TreeMap<>();

	/**
	 * 分发消息到处理者
	 * @param electricBicyclePacket
	 * @param channelContext
	 * @throws Exception
	 * @author: tanyaowu
	 */
	public void dispatch(PacketVo electricBicyclePacket, ChannelContext channelContext) throws Exception {
		Command command = electricBicyclePacket.getCommand();
		//		SessionContext sharebikeSessionContext = Utils.getSharebikeSessionContext(channelContext);
//		log.debug("{}, 收到命令:{}", channelContext, command);

		//不同的业务处理，在这里可以get不同的handle。
		ServerHandler handler = handlerMap.get(command);
		if (handler != null) {
//			log.debug("{} 收到消息:{}, isWebsocket:{}", channelContext, command);
			handler.handler(electricBicyclePacket, channelContext);
			return;
		} else {
//			log.warn("命令码[{}]没有对应的处理类", command);
			return;
		}
	}

	/**
	 * 
	 * @author: tanyaowu
	 */
	public PacketDispatcher(String[] scanPackages) {
		if (scanPackages != null) {
			for (String pkg : scanPackages) {
				try {
					ClassUtil.scanPackage(pkg, new ClassScanAnnotationHandler(CommandHandler.class) {
						@Override
						public void handlerAnnotation(Class<?> clazz) {
							try {
								Object bean = clazz.newInstance();

								if (!(bean instanceof ServerHandler)) {
									log.error("{}没有实现 {}", clazz.getName(), ServerHandler.class.getName());
									return;
								}

								ServerHandler imServerHandler = (ServerHandler) bean;

								CommandHandler mapping = clazz.getAnnotation(CommandHandler.class);
								Command command = mapping.value();

								Object obj = handlerMap.get(command);
								if (obj != null) {
									log.error("mapping[{}] already exists in class [{}]", command, obj.getClass().getName());
								} else {
									handlerMap.put(command, imServerHandler);
									pathClassMap.put(command, clazz);
								}

							} catch (Exception e) {
								log.error(e.toString(), e);
							}

						}
					});
				} catch (Exception e) {
					log.error(e.toString(), e);
				}
			}
			log.warn("command mapping\r\n{}", Json.toFormatedJson(pathClassMap));
		}
	}

	/**
	 * @param args
	 * @author: tanyaowu
	 */
	public static void main(String[] args) {

	}
}
